#pragma once

#include "Flyweight.h"

#include <initializer_list>
#include <unordered_map>

class FlyweightFactory
{
public:
    FlyweightFactory(std::initializer_list<SharedState> shared_states)
    {
        for (const SharedState &ss : shared_states) {
            this->m_flyweights.insert(std::pair<std::string, Flyweight>(getKey(ss), Flyweight(&ss)));
        }
    }

    ~FlyweightFactory()
    {
    }

public:
    Flyweight getFlyweight(const SharedState &shared_state)
    {
        std::string key = getKey(shared_state);
        if (m_flyweights.find(key) == m_flyweights.end()) {
            std::cout << "FlyweightFactory: Can't find a flyweight, creating new one." << std::endl;
            this->m_flyweights.insert(std::make_pair(key, Flyweight(&shared_state)));
        } else {
            std::cout << "FlyweightFactory: Reusing existing flyweight." << std::endl;
        }
        return this->m_flyweights.at(key);
    }

    void listFlyweights() const
    {
        size_t count = this->m_flyweights.size();
        std::cout << "\nFlyweightFactory: I have " << count << " flyweights:\n";
        for (std::pair<std::string, Flyweight> pair : this->m_flyweights) {
            std::cout << pair.first << std::endl;
        }
    }

private:
    std::string getKey(const SharedState &ss) const
    {
        return ss.m_brand + "_" + ss.m_model + "_" + ss.m_color;
    }

private:
    std::unordered_map<std::string, Flyweight> m_flyweights;
};